package cn.kgc.thread.demo3;

import java.util.concurrent.*;

/**
 * @description: 异步编排
 * @author: 石浩杰
 * @date: 2022-12-14 09:23
 */
public class Demo1 {
    private static ThreadPoolExecutor executor=new ThreadPoolExecutor(10,10,1, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());

    //whenComplete:有返回值，后面可以跟着exceptionally处理异常，处理异常。
    //handleAsync:无返回值，即使后面可以跟着exceptionally处理异常，也不执行。
    //thenApplyAsync:入参只能传入任务1的返回值
    //handleAsync:入参可以传入任务1的返回值与exception的信息
    //thenAcceptAsync
    //thenApplyAsync
    //thenRunAsync
    //thenCombineAsync
    //thenAcceptBothAsync
    //runAfterBothAsync
    //applyToEitherAsync
    //acceptEitherAsync
    //runAfterEitherAsync
    //allof
    public static void main(String[] args) throws Exception{
        CompletableFuture<String> future1=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return "任务1的返回值";
        },executor);
        CompletableFuture<String> future2=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(11000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行完毕");
            return "任务2的返回值";
        },executor);
        //CompletableFuture.allOf(future1,future2).join();
        //System.out.println("等待任务1和任务2执行完毕后执行");
        CompletableFuture.anyOf(future1,future2).join();
        System.out.println("只要有一个任务执行完毕后执行");
    }

    private static void extracted7() throws InterruptedException, ExecutionException {
        CompletableFuture<String> future1=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        },executor);
        CompletableFuture<String> future2=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        },executor);

        CompletableFuture<String> future3=future1.applyToEitherAsync(future2, result1 -> {
            System.out.println("执行任务3中的内容");
            System.out.println("任务3中的前两个任务中的一个任务返回值是:"+result1);
            return "任务3的返回值";
        },executor);
        System.out.println("任务3的返回值是:"+future3.get());

        CompletableFuture<Void> future4=future1.acceptEitherAsync(future2, result1 -> {
            System.out.println("执行任务4中的内容");
            System.out.println("任务4中的前两个任务中的一个任务返回值是:"+result1);
        },executor);

        CompletableFuture<Void> future5=future1.runAfterEitherAsync(future2, () -> {
            System.out.println("执行任务5中的内容");
        },executor);
    }

    private static void extracted6() throws InterruptedException, ExecutionException {
        CompletableFuture<String> future1=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        },executor);

        CompletableFuture<String> future2=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        },executor);

        CompletableFuture<String> future3=future1.thenCombineAsync(future2,(result1,result2)->{
            System.out.println("执行任务3中的内容，需要等待任务1和任务2执行完毕之后执行");
            System.out.println("在任务3中获得的任务1和任务2的返回值分别是："+result1+"和"+result2);
            return "任务3的返回值";
        },executor);
        System.out.println("任务3的返回值是："+future3.get());

        CompletableFuture<Void> future4=future1.thenAcceptBothAsync(future2,(result1,result2)->{
            System.out.println("执行任务4中的内容，需要等待任务1和任务2执行完毕之后执行");
            System.out.println("在任务4中获得的任务1和任务2的返回值分别是："+result1+"和"+result2);
        },executor);
        System.out.println("任务4的返回值是："+future4.get());

        CompletableFuture<Void> future5=future1.runAfterBothAsync(future2,()->{
            System.out.println("执行任务5中的内容，需要等待任务1和任务2执行完毕之后执行");
        },executor);
        System.out.println("任务5的返回值是："+future5.get());
    }

    private static void extracted5() {
        CompletableFuture<Void> completableFuture=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        },executor).thenRunAsync(()->{
            System.out.println("执行任务2中的内容");
        },executor);
    }

    private static void extracted4() {
        CompletableFuture<Void> completableFuture=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        },executor).thenAcceptAsync((result)->{
            System.out.println("执行任务2中的内容，任务2中获得的结果是:"+result);
        },executor);
    }

    private static void extracted3() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        },executor).thenApplyAsync((result)->{
            System.out.println("执行任务2中的内容,获得任务1的返回值："+result);
            return "任务2的返回值";
        },executor);
        System.out.println("最终获得的返回值是:"+completableFuture.get());
    }

    private static void extracted2() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
            System.out.println("任务1开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return "任务1的返回值";
        },executor).handleAsync((result,exception)->{
            System.out.println("任务2开始执行,任务2中接收到任务1的返回值:"+result);
            return "任务2的返回值";
        },executor);
        System.out.println(completableFuture.get());
    }

    private static void extracted1() throws InterruptedException, ExecutionException {
        //任务2要求在任务1执行完成以后执行，并且任务2 要使用任务1 的返回值
        CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
            String name=Thread.currentThread().getName();
            System.out.println(name+"任务开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name+"任务执行完毕");
            return "任务1返回的结果";
        },executor).whenCompleteAsync((result,exception)->{
            int temp=5/0;
            System.out.println("执行任务2的操作,在任务2中获得的任务1的返回值是"+result);
        },executor).exceptionally((exception)->{
            //前面任务出现异常时执行，任务1出现异常，任务2仍会执行，只不过任务2中获得的任务1中的结果是null
            System.out.println("任务中的异常信息"+exception.getMessage());
            return "异常处理后的返回值";
        });
        System.out.println(completableFuture.get());
    }

    private static void extracted() throws InterruptedException, ExecutionException {
        //有返回结果
        CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName()+"执行的任务1");
            return "任务1执行的结果";
        },executor);
        //任务1执行的结果
        System.out.println(completableFuture.get());
        //无返回结果
        CompletableFuture<Void> completableFuture2=CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread().getName()+"执行的任务1");
        },executor);
        //null
        System.out.println(completableFuture2.get());
    }
}
